<template>
  <t-link
    v-permission="['system:permission:assign-role-data-scope']"
    theme="primary"
    @click="handleOpenDialog('update', { ...props.row, roleId: props.row.id })"
  >
    数据权限
  </t-link>
  <!-- 自定义对话框 -->
  <custom-dialog
    ref="customDialogRef"
    v-slot="{ formData }"
    :api-map="{ update: setDataPermission }"
    header="数据权限"
    @request-success="handleDialogRequestSuccess"
  >
    <t-form-item label="角色名称" name="name" :rules="[{ required: true, message: '请输入角色名称' }]">
      <t-input v-model:value="formData.name" placeholder="请输入角色名称" clearable readonly />
    </t-form-item>
    <t-form-item label="角色标识" name="code" :rules="[{ required: true, message: '请输入角色标识' }]">
      <t-input v-model:value="formData.code" placeholder="请输入角色标识" clearable readonly />
    </t-form-item>
    <t-form-item label="权限范围" name="dataScope" :rules="[{ required: true, message: '请选择权限范围' }]">
      <t-select
        v-model:value="formData.dataScope"
        :options="dictionaryStore.get('system_data_scope', 'number')"
        placeholder="请选择权限范围"
        clearable
        filterable
        @clear="formData.dataScope = null"
      />
    </t-form-item>
    <t-form-item v-if="formData.dataScope === 2" label="部门范围" name="dataScopeDeptIds">
      <div>
        <t-space style="margin: 6px">
          是否全选<t-switch @change="handleChangeMenuChecked" /> 是否展开<t-switch @change="handleChangeMenuExpanded" />
        </t-space>
        <t-tree
          ref="deptTreeRef"
          v-model:value="formData.dataScopeDeptIds"
          :data="simpleDeptTree"
          :keys="{ value: 'id', label: 'name' }"
          checkable
          check-strictly
          @change="handleDeptIdsChange"
        />
      </div>
    </t-form-item>
  </custom-dialog>
</template>

<script setup lang="ts">
import { SwitchValue } from 'tdesign-vue-next';
import { ref, useTemplateRef } from 'vue';

import { getSimpleDeptList } from '@/api/system/dept';
import { setDataPermission } from '@/api/system/role';
import CustomDialog from '@/components/custom/dialog/index.vue';
import { useDictionaryStore } from '@/store';
import listToTree from '@/utils/listToTree';

// 字典仓库
const dictionaryStore = useDictionaryStore();
// props
const props = defineProps({
  row: {
    type: Object,
    default: () => ({}),
  },
});
// emits
const emits = defineEmits(['requestSuccess']);
// 精简部门树
const simpleDeptTree = ref([]);
// 处理获取精简部门树
const handleGetSimpleDeptTree = () => {
  getSimpleDeptList().then((data) => {
    simpleDeptTree.value = listToTree(data);
  });
};
// 自定义对话框ref
const customDialogRef = useTemplateRef('customDialogRef');
// 处理打开对话框
const handleOpenDialog = (mode: 'create' | 'read' | 'update', params: Record<string, any>) => {
  handleGetSimpleDeptTree();
  customDialogRef.value.open(mode, params);
};
// 处理对话框请求成功
const handleDialogRequestSuccess = (result: Record<string, any>) => {
  emits('requestSuccess', result);
};
// 部门树ref
const deptTreeRef = useTemplateRef('deptTreeRef');
// 是否操作部门
const isOperationDept = ref(false);
// 处理部门id改变
const handleDeptIdsChange = (_: any, { node }: any) => {
  if (isOperationDept.value) return;
  isOperationDept.value = true;
  const parents = deptTreeRef.value.getParents(node.value);
  parents.forEach((item) => {
    if (!item.checked) {
      deptTreeRef.value.setItem(item.value, { checked: true });
    }
  });
  const items = deptTreeRef.value.getItems(node.value);
  items.forEach((item) => {
    deptTreeRef.value.setItem(item.value, { checked: node.checked });
  });
  isOperationDept.value = false;
};
// 处理改变菜单选中
const handleChangeMenuChecked = (value: SwitchValue) => {
  if (isOperationDept.value) return;
  isOperationDept.value = true;
  const items = deptTreeRef.value.getItems();
  items.forEach((item) => {
    deptTreeRef.value.setItem(item.value, { checked: value as boolean });
  });
  isOperationDept.value = false;
};
// 处理改变菜单展开
const handleChangeMenuExpanded = (value: SwitchValue) => {
  if (isOperationDept.value) return;
  isOperationDept.value = true;
  const items = deptTreeRef.value.getItems();
  items.forEach((item) => {
    deptTreeRef.value.setItem(item.value, { expanded: value as boolean });
  });
  isOperationDept.value = false;
};
</script>

<style lang="less" scoped></style>
